local cjson = require "cjson"
local nmgpack = require "nmgpack"

local nmgpackx = {
	blocksize = 2,
	leftStr = {
		str = "",
		sz = 0,
	},
	debug = true,
}

function nmgpackx:new(o)
	o = o or {}	-- create object if user does not provide one
	setmetatable(o, self)
	self.__index = self
	o.leftStr = {
		str = "",
		sz = 0,
	}
	return o
end

local function dprint(...)
	if nmgpackx.debug then
		print(...)
	end
end

--[[
	send data :
		table data	--cjson->			json string
		json string	--nmgpackx->		stream,sz
		socket.write(stream,sz)

	receive data:
		socket.read(fd,2)	-->					steam head
		steam head			-->					steam head size
		socket.read(fd,size)-->					steam body
		steam body			--nmgpackx->	json string
		json string			--cjson->			table data
]]

--[[
	tdata 	: string
]]
function nmgpackx:pack(tdata)
	local jsonStr = cjson.encode(tdata)
	local streamb,bsz = jsonStr,#jsonStr
	-- 3rd lib can operation stream here
	local stream,sz = nmgpack.pack2stream(self.blocksize,streamb,bsz)
	return stream,sz
end

--[[
	msg 	: userdata
	sz 		: number
]]
function nmgpackx:newdata(msg,sz,num)
	-- sz is msg's size
	local bsize = self.blocksize
	-- rsz	-- left stream size 
	-- lmsg	-- left stream block 
	if self.leftStr.sz > 0 then
		-- TODO: maybe is wrong: to be test
		local lmsg = string.format("%s%s",self.leftStr.str,msg)
		local rsz = self.leftStr.sz + sz
		self.leftStr.str = ""
		self.leftStr.sz = 0
		msg = lmsg
		sz = rsz
	else
		-- self.leftStr is clear
	end
	dprint("nmgpackx:newdata msg",msg)
	dprint("nmgpackx:newdata sz",sz)
	local rs = {}
	while sz >= bsize do
		local bsz = nmgpack.unpack2streamh(bsize,msg,sz)
		local rsz = sz - bsize
		if rsz >=bsz then
			-- full data
			local fuldata,lmsg = nmgpack.unpack2streamb(bsize,msg,bsz)
			rsz = rsz - bsz
			msg = lmsg
			sz = rsz
			rs[#rs + 1] = {fuldata,bsz}
			if num and #rs >= num then
				break
			end
		else
			-- lack data (body)
			break
		end
	end
	-- lack data (head | body)
	self.leftStr.str = msg
	self.leftStr.sz = sz
	dprint("nmgpackx:newdata end",#rs)
	return rs
end

--[[

]]
function nmgpackx:combineUserdata(msg1,sz1,msg2,sz2)
	return nmgpack.combinestream(msg1,sz1,msg2,sz2)
end





return nmgpackx